"""
https://leetcode.cn/problems/binary-tree-maximum-path-sum/description/

124. 二叉树中的最大路径和
已解答
困难
相关标签
premium lock icon
相关企业
二叉树中的 路径 被定义为一条节点序列，序列中每对相邻节点之间都存在一条边。同一个节点在一条路径序列中 至多出现一次 。该路径 至少包含一个 节点，且不一定经过根节点。

路径和 是路径中各节点值的总和。

给你一个二叉树的根节点 root ，返回其 最大路径和 。

 

示例 1：


输入：root = [1,2,3]
输出：6
解释：最优路径是 2 -> 1 -> 3 ，路径和为 2 + 1 + 3 = 6
示例 2：


输入：root = [-10,9,20,null,null,15,7]
输出：42
解释：最优路径是 15 -> 20 -> 7 ，路径和为 15 + 20 + 7 = 42
 

提示：

树中节点数目范围是 [1, 3 * 104]
-1000 <= Node.val <= 1000

"""

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
from typing import Optional
from tree_node import TreeNode,build_tree_node


class Solution:

    """
    最大路径和
    注意点：
    1. 节点值可能为负值。因此需要遍历较多种情况
    2. 题目中未要求必须从根节点到根节点

    依旧，先按照dp思路考虑。
    每个子树，有两种最大路径和。
    1. 以根节点为一个端点的最大路径和
    2. 实际的最大路径和
    前者每个子树各自维护，后者则可全局比较获得
    
    dp(node)=max(dp(node.left),dp(node.right),0)+node.val
    max_sum(node)=max(max_sum(node.left),max_sum(node.right),node.val+dp(node.left)+dp(node.right))

    特殊的，如果node is None：
    dp(node)=max_sum(node)=0


    """

    def maxPathSum(self, root: Optional[TreeNode]) -> int:
        if not root:
            return 0
        
        dp_dict={}
        def calc_dp(node):
            if not node:
                return 0
            nonlocal dp_dict
            if node in dp_dict:
                return dp_dict[node]
            dp_val=max(calc_dp(node.left),calc_dp(node.right),0)+node.val
            dp_dict[node]=dp_val
            return dp_val
        
        max_sum=root.val

        def itr_max_sum(node):
            if not node:
                return 
            nonlocal max_sum
            if node.left:
                itr_max_sum(node.left)
            if node.right:
                itr_max_sum(node.right)
            sum=node.val+max(calc_dp(node.left),0)+max(calc_dp(node.right),0)
            # print(sum)
            max_sum=max(max_sum,sum)
        
        itr_max_sum(root)
        return max_sum


if __name__=='__main__':
    arr=[1,-2,3]
    root=build_tree_node(arr)

    s=Solution()
    res=s.maxPathSum(root)
    print(res)